package com.mindata.blockchain.core.dao.config;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * User: jasperxgwang
 * Date: 2018-8-2 14:05
 * <p>
 * 这里主要分三块：
 * <p>
 * 1 最上面的两个DataSource类，根据配置文件产生数据源，注意必须一个是Primary的，不然Spring会报错，因为找到了bean的两个实现，默认不知道选哪个
 * <p>
 * 2 中间的两个LocalContainerEntityManagerFactoryBean则是根据两个数据源产生对应的EntityManager，
 * 这里就可以做些hibernate的特定配置了，比如取名策略、sql方言之类的
 * <p>
 * 3 最后两个PlatformTransactionManager则是根据两个EntityManager产生对应的事务管理器，这样我们才能用事务
 */
@Configuration
public class DataSourceConfiguration {

    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.sqlite")
    @ConditionalOnProperty("block.analysis.sqlite")
    public DataSource sqliteDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.mysql")
    @ConditionalOnProperty("block.analysis.mysql")
    public DataSource mysqlDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "sqliteEntityManagerFactory")
    @Primary
    @ConditionalOnProperty("block.analysis.sqlite")
    public LocalContainerEntityManagerFactoryBean sqliteEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        LocalContainerEntityManagerFactoryBean em = builder
                .dataSource(sqliteDataSource())
                .packages("com.mindata.blockchain.core.model")
                .persistenceUnit("sqlite")
                .build();
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", "com.mindata.blockchain.core.sqlite.config.SQLiteDialect");
        em.setJpaProperties(properties);
        return em;
    }

    @Bean(name = "mysqlEntityManagerFactory")
    @ConditionalOnProperty("block.analysis.mysql")
    public LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        LocalContainerEntityManagerFactoryBean em = builder
                .dataSource(mysqlDataSource())
                .packages("com.mindata.blockchain.core.model")
                .persistenceUnit("mysql")
                .build();
        Properties properties = new Properties();
        em.setJpaProperties(properties);
        return em;
    }

    @Bean(name = "sqliteTransactionManager")
    @Primary
    @ConditionalOnProperty("block.analysis.sqlite")
    PlatformTransactionManager mssqlTransactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(sqliteEntityManagerFactory(builder).getObject());
    }

    @Bean(name = "mysqlTransactionManager")
    @Primary
    @ConditionalOnProperty("block.analysis.mysql")
    PlatformTransactionManager mysqlTransactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(mysqlEntityManagerFactory(builder).getObject());
    }
}